package com.cdxy.service.impl;

import com.cdxy.dmr.dataObject.SmsVerifyLogDO;
import com.cdxy.dmr.repository.SmsVerifyLogRepository;
import com.cdxy.enums.BizErrorEnum;
import com.cdxy.enums.KaptchaEnum;
import com.cdxy.model.dto.base.exception.BusinessException;
import com.cdxy.service.IEmailService;
import com.sun.mail.util.MailSSLSocketFactory;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.security.GeneralSecurityException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Properties;

/**
 * @Author: tangy
 * @Date: 2020/2/23 17:03
 */
@Service
public class EmailServiceImpl implements IEmailService {

    @Autowired
    private SmsVerifyLogRepository smsVerifyLogRepository;

    @Value("${spring.mail.username}")
    private String from;

    @Value("${spring.mail.password}")
    private String password;

    @Value("${spring.mail.protocol}")
    private String protocol;

    @Value("${spring.mail.port}")
    private String port;

    @Value("${spring.mail.host}")
    private String host;

    /**
     * 失效时间：单位 分
     */
    private Integer expireTime = 5;

    public JavaMailSender mailSender;

    EmailServiceImpl(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    @Override
    public void sendEmail(KaptchaEnum.BusinessCode businessCode, String email) {
        String code = RandomStringUtils.randomNumeric(6);
        this.sendMail(email, code, businessCode);

        // 保存数据库
        SmsVerifyLogDO smsVerifyLogDO = new SmsVerifyLogDO();
        smsVerifyLogDO.setBusinessType(KaptchaEnum.Type.EMAIL.name());
        smsVerifyLogDO.setCode(code);
        smsVerifyLogDO.setMobile(email);
        smsVerifyLogDO.setScene(businessCode.name());
        smsVerifyLogRepository.save(smsVerifyLogDO);
    }

    @Override
    public void verifyEmail(KaptchaEnum.BusinessCode businessCode, String email, String code) {
        SmsVerifyLogDO smsVerifyLogDO = smsVerifyLogRepository.getByBusinessTypeAndSceneAndMobileOrderBySceneOrderByIdDesc(KaptchaEnum.Type.EMAIL.name(), businessCode, email);
        if (smsVerifyLogDO == null || smsVerifyLogDO.getVerifyTime() != null) {
            throw new BusinessException(BizErrorEnum.VERIFICATION_CODE_ERROR, "请先获取验证码");
        }
        // 比对时间和正确性
        if (smsVerifyLogDO.getCreateTime().plusMinutes(expireTime).isBefore(LocalDateTime.now())) {
            throw new BusinessException(BizErrorEnum.VERIFICATION_CODE_TIMEOUT_ERROR);
        }
        if (!smsVerifyLogDO.getCode().equalsIgnoreCase(code)) {
            throw new BusinessException(BizErrorEnum.VERIFICATION_CODE_ERROR);
        }
        SmsVerifyLogDO smsVerifyLogUpdateDO = new SmsVerifyLogDO();
        smsVerifyLogUpdateDO.setId(smsVerifyLogDO.getId());
        smsVerifyLogUpdateDO.setVerifyTime(LocalDateTime.now());
        smsVerifyLogRepository.updateById(smsVerifyLogUpdateDO);
    }

    public Session initProperties() {
        Properties properties = new Properties();
        properties.setProperty("mail.transport.protocol", protocol);
        properties.setProperty("mail.smtp.host", host);
        properties.setProperty("mail.smtp.port", port);
        // 使用 smtp 身份验证
        properties.put("mail.smtp.auth", "true");
        // 使用 SSL，企业邮箱必须 start
        // 开启安全协议
        MailSSLSocketFactory mailSSLSocketFactory = null;
        try {
            mailSSLSocketFactory = new MailSSLSocketFactory();
            mailSSLSocketFactory.setTrustAllHosts(true);
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        properties.put("mail.smtp.enable", "true");
        properties.put("mail.smtp.ssl.socketFactory", mailSSLSocketFactory);
        properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        properties.put("mail.smtp.socketFactory.fallback", "false");
        properties.put("mail.smtp.socketFactory.prot", port);
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(from, password);
            }
        });
        // 使用 SSL, 企业邮箱必须 end
        return session;
    }

    public void sendMail(String to, String randomNumber, KaptchaEnum.BusinessCode businessCode) {
        try {
            Session session = initProperties();
            MimeMessage mimeMessage = new MimeMessage(session);
            mimeMessage.setFrom(new InternetAddress(from, "tangy"));
            InternetAddress[] internetAddressesTo = new InternetAddress().parse(to);
            mimeMessage.setRecipients(Message.RecipientType.TO, internetAddressesTo);
            // 主题
            mimeMessage.setSubject("验证码");
            // 时间
            mimeMessage.setSentDate(new Date());
            // 容器类 附件
            MimeMultipart mimeMultipart = new MimeMultipart();
            // 可以包装文本,图片,附件
            MimeBodyPart bodyPart = new MimeBodyPart();
            // 设置内容 getEmailHtml是邮箱内容模板
            bodyPart.setContent(getEmailHtml(to, randomNumber, businessCode), "text/html; charset=UTF-8");
            mimeMultipart.addBodyPart(bodyPart);
            // 添加图片&附件
//            bodyPart = new MimeBodyPart();
//            bodyPart.attachFile(fileSrc);
//            mimeMultipart.addBodyPart(bodyPart);
            mimeMessage.setContent(mimeMultipart);
            mimeMessage.saveChanges();
            Transport.send(mimeMessage);
        } catch (Exception e) {
            throw new BusinessException(BizErrorEnum.SEND_EMAIL_ERROR);
        }
    }

    public String getEmailHtml(String to, String code, KaptchaEnum.BusinessCode businessCode) {
        String[] tos = to.split("@");
        String sub = tos[0].substring(0, 2);
        String email = sub + "*******@" + tos[1];
        String html = "<div style=\"padding: 0px 0px 0px 20px;box-sizing: border-box;color: #333333;font-family: \"microsoft yahei\";font-size: 14px\">" +
                "<h4 style=\"color:#2672EC;font-size: 40px;margin-top: 24px;font-weight: normal;\">账号验证码</h4>" +
                "<div style=\"margin-top: 40px;\">您好<a href=\"javascript:;\" target=\"_blank\" style=\"color: #2672EC;text-decoration: none;\">" + email + "</a>。</div>" +
                "<div style=\"margin-top: 40px;\">您正在" + businessCode.getDesc() + "</div>" +
                "<div style=\"margin-top: 30px;\">您的验证码为：<em style=\"font-style: normal;font-weight: 600;\">" + code + "</em></div>" +
                "<div style=\"margin-top: 35px;\">谢谢！</div>" +
                "</div>";
        return html;
    }
}
